﻿using FastSocket.Server;
using FastSocket.Server.Protocol;
using FastSocket.SocketBase;
using SocketTool.Com.Args;
using SocketTool.Model.DataModels;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SocketTool.Com.TCP.Server
{
    public class TCPServer : SocketServer<TCPServerMessage>, ISocket
    {
        private TCPServerProtocol mProtocol;
        private TCPServerDataModel mSocketModel;
        private TCPService mService;

        public event EventHandler<ConnectionArgs> SocketConnectionChangedEvent;
        public event EventHandler<ReceiveMessageArgs> ReceiveMessageEvent;

        public TCPServer(TCPServerDataModel socket)
    : this(socket.ListenPort,
          new TCPService(),
          new TCPServerProtocol(),
          socket.SocketBufferSize,
          socket.MsgBufferSize,
          102400,
          20000)
        {
            if (socket == null) throw new ArgumentNullException("socket");
            this.mSocketModel = socket;
        }

        public TCPServer(int port,
           ISocketService<TCPServerMessage> service,
           IProtocol<TCPServerMessage> protocol,
           int socketBufferSize,
           int messageBufferSize,
           int maxMessageSize,
           int maxConnections)
           : base(port, service, protocol, socketBufferSize, messageBufferSize, maxMessageSize, maxConnections)
        {
            this.mProtocol = (TCPServerProtocol)protocol;
            this.mService = (TCPService)service;
            this.mService.SetTCPServer(this);
        }


        public void Close()
        {
            this.Stop();
        }

        public bool Open()
        {
            this.Start();
            return true;
        }

        public void Send(string msg, int count)
        {
            var bt = Encoding.UTF8.GetBytes(msg);
            var sendBt = this.mProtocol.Protocols.GetSendData(bt);

      
        }



        public void SetCustomerProtocol(CustomerProtocol protocol)
        {
            this.mProtocol.Protocols = protocol;
        }


        public class TCPService : AbsSocketService<TCPServerMessage>
        {
            private TCPServer mServer;
            public ConcurrentDictionary<long, IConnection> OnLineConnections = new ConcurrentDictionary<long, IConnection>();

            public void SetTCPServer(TCPServer server)
            {
                this.mServer = server;
            }

            /// <summary>
            /// 当连接时会调用此方法
            /// </summary>
            /// <param name="connection"></param>
            public override void OnConnected(IConnection connection)
            {
                base.OnConnected(connection);
                OnLineConnections.TryAdd(connection.ConnectionID, connection);
                this.mServer.SocketConnectionChangedEvent?.Invoke(this, new Args.ConnectionArgs(connection));
                connection.BeginReceive();
            }

            public override void OnSendCallback(IConnection connection, Packet packet, bool isSuccess)
            {
                base.OnSendCallback(connection, packet, isSuccess);
                Console.WriteLine("发送消息回调事件！");
            }

            /// <summary>
            ///
            /// </summary>
            /// <param name="connection"></param>
            /// <param name="message"></param>
            public override void OnReceived(IConnection connection, TCPServerMessage message)
            {
                base.OnReceived(connection, message);
                this.mServer.ReceiveMessageEvent?.Invoke(this, new Args.ReceiveMessageArgs(null,Encoding.UTF8.GetString(message.Payload)));
                Console.WriteLine(Encoding.UTF8.GetString(message.Payload));
            }

            /// <summary>
            /// 当连接断开时会调用此方法
            /// </summary>
            /// <param name="connection"></param>
            /// <param name="ex"></param>
            public override void OnDisconnected(IConnection connection, Exception ex)
            {
                base.OnDisconnected(connection, ex);
                IConnection outConnection;
                OnLineConnections.TryRemove(connection.ConnectionID, out outConnection);
                this.mServer.SocketConnectionChangedEvent?.Invoke(this, new Args.ConnectionArgs(connection));
            }

            /// <summary>
            /// 当发生错误时会调用此方法
            /// </summary>
            /// <param name="connection"></param>
            /// <param name="ex"></param>
            public override void OnException(IConnection connection, Exception ex)
            {
                base.OnException(connection, ex);
                IConnection outConnection;
                OnLineConnections.TryRemove(connection.ConnectionID, out outConnection);
                this.mServer.SocketConnectionChangedEvent?.Invoke(this, new Args.ConnectionArgs(connection));
            }
        }
    }
}
